-- Copyright (c) 2025 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--         http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

local class = require 'mc.class'
local log = require 'mc.logging'

local m = class()

local CUSTOM_TYPE<const> = "SPU"

local function record_customize_operation_log(ctx, msg)
    if ctx and not ctx:is_empty() then
        log:operation(ctx:get_initiator(), 'pcie_device', msg)
    end
end

local function set_npucard_custom_string(db, ctx, custom_str)
    if not custom_str then
        log:error('npucard custom str is null')
        return false
    end
    log:notice('set npucard custom string to %s', custom_str)
    if #custom_str ~= 0 and custom_str ~= "SPU" and custom_str ~= 'NPU' then
        log:error("NPUCard's custom name just support set to SPU or NPU")
        return false
    end

    local dest_enable = custom_str == CUSTOM_TYPE
    local tbl = db.PCIeCardDisplayCustom
    local records = db:select(tbl):where(tbl.CustomType:eq(CUSTOM_TYPE)):all()
    if records == nil or #records == 0 then
        log:notice("There is no NPUCard that requires SPU customization")
        return true
    end
    for _, record in ipairs(records) do
        record.Enabled = dest_enable
        record:save()
        log:notice("[manufacture_npucard] Update persistance PCIeCardDisplayCustom, QuadrupleId=%s, CustomType=%s, \
            CardType=%s, Enabled=%s", record.QuadrupleId, record.CustomType, record.CardType, record.Enabled)
    end
    return true
end

local import_callback_map = {
    ['BMCSet_AtlasCustomString'] = set_npucard_custom_string
}

function m.on_import(db, ctx, customize_data)
    local ok, ret
    for item, v in pairs(customize_data) do
        if not import_callback_map[item] then
            log:error('Import %s has no object to process.', item)
        else
            ok, ret = pcall(import_callback_map[item], db, ctx, v.Value)
            if not ok or not ret then
                record_customize_operation_log(ctx, string.format('Set %s through customization failed', item))
                log:error("Import %s has error occured (%s).", item, ret)
            else
                record_customize_operation_log(ctx, string.format('Set %s through customization successfully', item))
                log:notice("Import %s successfully.", item)
            end
        end
    end
end

function m.on_export(db, ctx)
    log:notice("NpuCard's custom config export start")
    local data = {}
    local tbl = db.PCIeCardDisplayCustom
    local record = db:select(tbl):where(tbl.CustomType:eq(CUSTOM_TYPE)):first()
    if record == nil then
        log:notice("There is no NPUCard requires SPU customization")
        data.BMCSet_AtlasCustomString = 'NPU'
        return data
    end
    log:notice("npucard custom string export value: %s", record.Enabled)
    data.BMCSet_AtlasCustomString = record.Enabled and CUSTOM_TYPE or 'NPU'
    return data
end

return m